package com.example.searchservice.repository;

import co.elastic.clients.elasticsearch._types.query_dsl.*;
import co.elastic.clients.json.JsonData;
import org.springframework.data.elasticsearch.core.query.StringQuery;

import java.util.Arrays;
import java.util.List;

public class ElasticsearchQueryUtils {

    /**
     * 创建多字段匹配查询（替代旧的 QueryBuilders.multiMatchQuery）
     */
    public static Query buildMultiMatchQuery(String keyword, String... fields) {
        return Query.of(q -> q
                .multiMatch(m -> m
                        .query(keyword)
                        .fields(Arrays.asList(fields))
                        .analyzer("ik_max_word")
                )
        );
    }

    /**
     * 创建匹配查询（替代旧的 QueryBuilders.matchQuery）
     */
    public static Query buildMatchQuery(String field, String value) {
        return Query.of(q -> q
                .match(m -> m
                        .field(field)
                        .query(value)
                        .analyzer("ik_max_word")
                )
        );
    }

    public static Query buildSmartMatchQuery(String field, String value) {
        return Query.of(q -> q
                .match(m -> m
                        .field(field)
                        .query(value)
                        .analyzer("ik_smart")
                        .operator(Operator.And)
                )
        );
    }

    /**
     * 使用 NGram 进行单字搜索
     */
    public static Query buildNgramQuery(String field, String value) {
        return Query.of(q -> q
                .match(m -> m
                        .field(field + ".ngram")
                        .query(value)
                )
        );
    }


    /**
     * 使用 Edge NGram 进行前缀搜索
     */
    public static Query buildEdgeQuery(String field, String value) {
        return Query.of(q -> q
                .match(m -> m
                        .field(field + ".edge")
                        .query(value)
                )
        );
    }

    /**
     * 混合搜索：IK分词 + NGram
     * .minimumShouldMatch("2")      // 必须匹配2个条件
     * .minimumShouldMatch("1")      // 必须匹配1个条件（默认）
     * .minimumShouldMatch("0")      // 可以不匹配任何条件
     *
     * .minimumShouldMatch("50%")    // 必须匹配50%的条件
     * .minimumShouldMatch("75%")    // 必须匹配75%的条件
     *
     * .minimumShouldMatch("3<90%")  // 条件数≤3时需全部匹配，>3时匹配90%
     * .minimumShouldMatch("2<-25%") // 复杂组合条件
     */
    public static Query buildIkNgramQuery(String field, String value) {
        return Query.of(q -> q
                .bool(b -> b
                        .should(s -> s
                                .match(m -> m
                                        .field(field)
                                        .query(value)
                                        .analyzer("ik_smart")
                                )
                        )
                        .should(s -> s
                                .match(m -> m
                                        .field(field + ".ngram")
                                        .query(value)
                                )
                        )
                        .minimumShouldMatch("1")
                )
        );
    }

    /**
     * 创建术语查询（替代旧的 QueryBuilders.termQuery）
     */
    public static Query buildTermQuery(String field, String value) {
        return Query.of(q -> q
                .term(t -> t
                        .field(field)
                        .value(value)
                )
        );
    }

    /**
     * 创建模糊查询（替代旧的 QueryBuilders.fuzzyQuery）
     */
    /**
     * 构建模糊匹配查询
     */
    public static Query buildFuzzyMatchQuery(String field, String value) {
        return Query.of(q -> q
                .match(m -> m
                        .field(field)
                        .query(value)
                        .fuzziness("AUTO")
                        .prefixLength(1)
                        .maxExpansions(chooseMaxExpansions(value.length()))
                        .analyzer("ik_max_word")
                )
        );
    }

    private static int chooseMaxExpansions(int wordLength) {
        if (wordLength <= 3) return 20;    // 短词：较少扩展
        if (wordLength <= 6) return 50;    // 中等词：适中扩展
        if (wordLength <= 10) return 100;  // 长词：较多扩展
        return 150;                        // 很长词：大量扩展
    }

    /**
     * 构建专门的模糊查询
     */
    public static Query buildFuzzyQuery(String field, String value) {
        return Query.of(q -> q
                .fuzzy(f -> f
                        .field(field)
                        .value(value)
                        .fuzziness("AUTO")
                        .prefixLength(1)
                )
        );
    }

    public static Query buildRangeQuery(String field, Double min, Double max) {
        return Query.of(q -> q
                .range(r -> r
                        .field(field)
                        .gte(JsonData.of(min))
                        .lte(JsonData.of(max))
                )
        );
    }

    /**
     * 创建布尔查询（替代旧的 QueryBuilders.boolQuery）
     */
    public static Query buildBoolQuery(List<Query> mustClauses, List<Query> shouldClauses) {
        return Query.of(q -> q
                .bool(b -> {
                    if (mustClauses != null && !mustClauses.isEmpty()) {
                        b.must(mustClauses);
                    }
                    if (shouldClauses != null && !shouldClauses.isEmpty()) {
                        b.should(shouldClauses);
                    }
                    return b;
                })
        );
    }

    /**
     * 构建布尔查询
     */
    public static Query buildBooFilterlQuery(List<Query> must, List<Query> filter) {
        return Query.of(q -> q
                .bool(b -> {
                    if (must != null && !must.isEmpty()) {
                        b.must(must);
                    }
                    if (filter != null && !filter.isEmpty()) {
                        b.filter(filter);
                    }
                    return b;
                })
        );
    }

    public static org.springframework.data.elasticsearch.core.query.Query buildStringQuery(String name, String category, Double minPrice, Double maxPrice) {
        String queryJson = String.format("""
            {
              "query": {
                "bool": {
                  "must": [
                    {
                      "match": {
                        "name": {
                          "query": "%s",
                          "analyzer": "ik_max_word"
                        }
                      }
                    }
                  ],
                  "filter": [
                    {
                      "term": {
                        "category": "%s"
                      }
                    },
                    {
                      "range": {
                        "price": {
                          "gte": %s,
                          "lte": %s
                        }
                      }
                    }
                  ]
                }
              }
            }
            """, name, category, minPrice, maxPrice);

        org.springframework.data.elasticsearch.core.query.Query query = new StringQuery(queryJson);
        return query;
    }

    /**
     * 构建通配符查询
     */
    public static Query buildWildcardQuery(String field, String pattern) {
        return Query.of(q -> q
                .wildcard(w -> w
                        .field(field)
                        .value(pattern)
                        .caseInsensitive(true)
                )
        );
    }

    /**
     * 构建包含搜索的通配符查询
     */
    public static Query buildContainsQuery(String field, String text) {
        return buildWildcardQuery(field, "*" + text + "*");
    }

    /**
     * 构建前缀搜索查询
     */
    public static Query buildPrefixQuery(String field, String prefix) {
        return buildWildcardQuery(field, prefix + "*");
    }

    /**
     * 构建后缀搜索查询
     */
    public static Query buildSuffixQuery(String field, String suffix) {
        return buildWildcardQuery(field, "*" + suffix);
    }

    /**
     * 构建短语匹配查询
     * slop = 0：严格短语匹配，词语必须完全按顺序出现
     *
     * slop = 1：允许词语之间有1个位置的移动
     *
     * slop = 2：允许词语之间有2个位置的移动
     *
     * slop = N：允许词语之间有N个位置的移动
     */
    public static Query buildMatchPhraseQuery(String field, String query) {
        return Query.of(q -> q
                .matchPhrase(m -> m
                        .field(field)
                        .query(query)
                        .slop(2)    // 允许2个词语的间隔
                        .analyzer("ik_max_word")    // 索引时分词器
                )
        );
    }

    /**
     * 构建短语前缀查询（自动补全）
     */
    public static Query buildMatchPhrasePrefixQuery(String field, String query) {
        return Query.of(q -> q
                .matchPhrasePrefix(m -> m
                        .field(field)
                        .query(query)
                        .slop(2)
                        .analyzer("ik_max_word")
                        .maxExpansions(10) // 最大扩展数
                )
        );
    }
}